from prettytable import PrettyTable
from scipy.stats import hypergeom
import matplotlib.pyplot as plt


def factorial (n): #функция факториала для нахождения C
    if n == 0 or n == 1:
        return 1
    else:
        return n * factorial(n - 1)

def hypergeometric_probability(N, K, n, x): # функция для поиска вероятности для конкретного значения X
    numerator = factorial(K) * factorial(N - K) * factorial(n) * factorial(N - n)
    denominator = factorial(N) * factorial(x) * factorial(K - x) * factorial(n - x) * factorial(N - K - n + x)
    probability = numerator / denominator
    return probability

def hypergeometric_distribution(N, K, n): #функция для вычисления гипергеометрической функции для параметров N, K, n
    distribution = []
    for x in range(max(0, n - N + K), min(n, K) + 1):
        probability = hypergeometric_probability(N, K, n, x)
        distribution.append((x, probability))
    return distribution


N=20
K=8
n=12

hypergeom_dist=hypergeometric_distribution(N,K,n)
cumulative_dist=0

table_for_disk=PrettyTable()
table_for_disk.field_names = ["x", "P(X=x)", "F(X=x)"]

x_val=[]
P_val=[]
F_val=[]

for x, probability in hypergeom_dist:
    cumulative_dist += probability
    x_val.append(x)
    P_val.append(probability)
    F_val.append(cumulative_dist)
    table_for_disk.add_row([x, f"{probability:.5f}", f"{cumulative_dist:.5f}"])


print(table_for_disk)

x_values = range(max(0, n - N + K), min(n, K) + 1)

hypergeom_dist = hypergeom.pmf(x_values, N, K, n)
hypergeom_dist_F=hypergeom.cdf(x_values, N, K, n)

# Создание таблицы
table = PrettyTable()
table.field_names = ["X", "P(X)", "F(X)"]

# Заполнение таблицы и вывод результатов
for x, probability, cumulative_F in zip(x_values, hypergeom_dist,hypergeom_dist_F):
    table.add_row([x, f"{probability:.5f}", f"{cumulative_F:.5f}"])


print(table)



# Define the width of the bars
bar_width = 0.4

# Plotting Probability Distribution (P(X))
plt.bar([x-(bar_width/2) for x in x_val], P_val, width=bar_width, color='blue', alpha=0.7, label='P(X)')

# Plotting Cumulative Distribution (F(X)) by adjusting x positions
plt.bar([x+(bar_width/2) for x in x_val], F_val, width=bar_width, color='green', alpha=0.7, label='F(X)')

plt.title('Гипергеометрическое распределение')
plt.legend()
plt.show()
